#include "GARunner.h"
#include <stdlib.h>
#include <iostream>
#include <time.h>

using namespace std;


GARunner::GARunner(double pc, double pm, int iterNum, CoverageTable *ct)
	:Runner(iterNum,ct)
{
	crossover=new Crossover(pc);
	mutate=new Mutate(pm);
	survive=new Survive();
}

GARunner::~GARunner()
{
	delete crossover;
	delete mutate;
	delete survive;
}

int GARunner::run(vector<vector<int>> &pop, vector<int>& limit)
{
	int dim=pop[0].size();
	int maxCombNum=dim*(dim-1)>>1;
	size_t popsize=pop.size();      //size of the population
	size_t numofIter=popsize>>1;    //size of the child population
	int iternum=GetMaxIter();
	vector<int> pFitVec;
	for(int i=0;i<popsize;i++)
		pFitVec.push_back(0);
	for(int i=0;i<iternum;i++)
	{
		GetEvaluator()->run(pop,pFitVec);
		for(int j=0;j<pFitVec.size();j++)
		{
			if(pFitVec[j]==maxCombNum)
				return j;
		}
		srand(clock());
		vector<vector<int>> childpop;
		vector<int> cFitVec;
		for(int j=0;j<popsize;j++)
			cFitVec.push_back(0);
		for(int j=0;j<numofIter;j++)
		{
			vector<int> ind1=pop[rand()%popsize];
			vector<int> ind2=pop[rand()%popsize];
			crossover->run(ind1, ind2);             //crossover
			mutate->run(ind1,limit);                //mutate
			mutate->run(ind2,limit);
			childpop.push_back(ind1);
			childpop.push_back(ind2);
		}
		GetEvaluator()->run(childpop,cFitVec);
		survive->run(pop,pFitVec,childpop,cFitVec);
		/////////for debug///////////////
		/*for(int index=0;index<popsize;index++)
		{
			if(pop[index][0]==2&&pop[index][14]==3)
				cout<<"bazinga case: 0, 14, 2, 3"<<"\n";
			if(pop[index][3]==2&&pop[index][14]==3)
				cout<<"bazinga case: 3, 14, 2, 3"<<"\n";
		}*/
		/////////////////////////////////
	}
	int ret=0;
	for(int i=1;i<popsize;i++)         //search for the max fitness value
	{
		if(pFitVec[i]>pFitVec[ret])
			ret=i;
	}
	if(pFitVec[ret]==0)
		return -1;
	return ret;
}